package com.functest.orm

import groovy.sql.Sql
import groovy.transform.ToString
import org.testng.annotations.Test

import static com.functest.orm.MapperUtil.transform

/**
 * @author: DavydovMD
 * Date: 05.04.13
 * Time: 14:10
 */

class SampleTest {
    final static Sql testDb
    static {
        Class.forName('org.sqlite.JDBC');
        testDb = Sql.newInstance('jdbc:sqlite::memory:', 'org.sqlite.SQLite')
        testDb.with {
            withTransaction {
                execute("CREATE table student as select 1 as id, 'Ivan                                 ' as first_name, 'Ivanov                                 ' as lastName, 'Graduate               ' as status")
                execute('delete from student')
                execute("insert into student values(2,'Ivan','Ivanov','Graduate')")
                execute("insert into student values(3,'Sidor','Sidorov','Student')")
                execute("insert into student values(4,'Petr','Petrov','Expelled')")
                commit()
            }
        }
        int res = testDb.firstRow('select count(*) from student').values().iterator().next() as int
        assert res == 3
    }

    static enum StudentStatus {
        Graduate, Student, Expelled
    }

    @ToString(includeFields = true)
    static class Student {
        /* Fields */
        int id
        String firstName
        String lastName
        StudentStatus status

        /* Mapper */
        static SingleDbTableMapper<Student> mapper =
            new SingleDbTableMapper<Student>(
                    new MapperFields().build {
                        field('id')
                        field('firstName', 'first_name')
                        field('lastName')
                        field('status', 'status', transform.stringEnum(StudentStatus), com.functest.orm.MapperUtil.transformBack.stringEnum(StudentStatus))
                    }
                    , { SampleTest.testDb }
                    , 'student'
                    , 'id'
                    , Student
            )

        /* Provider */
        static BaseProvider<Student> provider = new BaseProvider<Student>(Student, [Student.mapper])
    }

    @Test
    void byIdTest() {
        def ivanov = Student.provider.byId(2)
        assert ivanov.firstName == 'Ivan'
        assert ivanov.lastName == 'Ivanov'
        assert ivanov.status == StudentStatus.Graduate
    }

    @Test
    void byFieldValueFirst() {
        Student petrov = Student.provider.byFieldValueFirst('lastName', 'Petrov')
        assert petrov.firstName == 'Petr'
        assert petrov.status == StudentStatus.Expelled
    }


    @Test
    void usingQueryTest() {
        def query = Student.provider.query()
        QueryExecutor qe = query.allFields()
                .where('firstName', com.functest.orm.ConditionOp.EQ, 'Ivan')
                .or('status', com.functest.orm.ConditionOp.EQ, StudentStatus.Expelled)
                .build()
        List<Student> students = Student.provider.usingQuery(qe)
        assert students.size() == 2
        assert students.findAll { it.status == StudentStatus.Expelled }.size() == 1
        assert students.findAll { it.firstName == 'Ivan' }.size() == 1
    }

    @Test
    void usingFiltersTest() {
        assert Student.provider.usingFilters([Condition.of('firstName', ConditionOp.LIKE, '%va%')]).size() == 1
        assert Student.provider.usingFilters([Condition.of('status', ConditionOp.NOT_IN, [StudentStatus.Expelled, StudentStatus.Graduate])]).size() == 1
    }

    @Test
    void usingFilteringClosuresTest() {
        def students =
            Student.provider.usingFilteringClosures([
                    { WhereClauseBuilder wb -> wb.and('firstName', com.functest.orm.ConditionOp.EQ, 'Ivan') }
                    , { WhereClauseBuilder wb -> wb.or('status', com.functest.orm.ConditionOp.EQ, StudentStatus.Expelled) }
            ])
        assert students.size() == 2
        assert students.findAll { it.status == StudentStatus.Expelled }.size() == 1
        assert students.findAll { it.firstName == 'Ivan' }.size() == 1
    }

}